﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Linq;

using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.DataSourcesFile;
using ESRI.ArcGIS.DataSourcesGDB;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Output;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.Geoprocessing;
using ESRI.ArcGIS.AnalysisTools;

using MyEngineExercise.我的扩展.图层扩展类;
using MyEngineExercise.我的扩展.自定义事件参数类;
using MyEngineExercise.我的扩展.枚举;
using MyEngineExercise.我的扩展.信息类;
using ESRI.ArcGIS.Geoprocessor;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.ArcMapUI;
using stdole;

namespace MyEngineExercise.我的扩展
{
    public class MyAeMethods
    {
        /// <summary>
        /// 单件类
        /// </summary>
        private static MyAeMethods _instance = null;
        public static MyAeMethods Instance{get { return _instance; }}


        private MainForm _mainForm = null;
        private IMapControl3 _mapControl = null;
        private IPageLayoutControl3 _pageLayoutControl = null;
        private ITOCControl2 _tocControl = null;
        private IToolbarControl2 _toolbarControl = null;

        
        //自定义事件
        public event EventHandler<LayerChangingEventArgs> LayerChanging = null;
        public event EventHandler<LayerChangedEventArgs> LayerChanged = null;



        /// <summary>
        /// 创建实例
        /// </summary>
        public static MyAeMethods CreateInstance(MainForm mainForm, IMapControl3 mapControl, IPageLayoutControl3 pageLayoutControl, ITOCControl2 tocControl, IToolbarControl2 toolbarControl)
        {
            if (null == _instance)
                _instance = new MyAeMethods(mainForm, mapControl, pageLayoutControl, tocControl, toolbarControl);
            return _instance;

        }


        /// <summary>
        /// 私有构造函数
        /// </summary>
        private MyAeMethods(MainForm mainForm,IMapControl3 mapControl,IPageLayoutControl3 pageLayoutControl,ITOCControl2 tocControl,IToolbarControl2 toolbarControl)
        {
            _mainForm = mainForm;
            _mapControl = mapControl;
            _pageLayoutControl = pageLayoutControl;
            _tocControl = tocControl;
            _toolbarControl = toolbarControl;
        }



        #region Workspace

        /// <summary>
        /// 返回featureclass的Workspace
        /// </summary>
        /// <param name="featureClass"></param>
        public IWorkspace NewWorkspace(IFeatureClass featureClass)
        {
            IDataset dataset = (IDataset)featureClass;
            return dataset.Workspace;
        }


        /// <summary>
        /// 根据shape路径，打开一个 要素工作空间 并返回IFeatureWorkspace
        /// </summary>
        /// <param name="shapeFullPath">shape文件完整路径</param>
        public IFeatureWorkspace NewShapeFeatureWorkspace(string shapeFullPath)
        {
            IWorkspaceFactory workspaceFactory = null;
            IFeatureWorkspace featureWorkspace = null;
            workspaceFactory = new ShapefileWorkspaceFactoryClass();
            string workspacePath = System.IO.Path.GetDirectoryName(shapeFullPath);//shape所在文件夹路径
            featureWorkspace = (IFeatureWorkspace)workspaceFactory.OpenFromFile(workspacePath, 0);
            
            return featureWorkspace;
        }


        /// <summary>
        /// 根据mdb路径，打开一个 已存在的要素工作空间 并返回IFeatureWorkspace
        /// </summary>
        /// <param name="mdbFullPath"></param>
        /// <returns></returns>
        public IFeatureWorkspace NewMdbFeatureWorkspace(string mdbFullPath)
        {
            IWorkspaceFactory workspaceFactory = null;
            IFeatureWorkspace featureWorkspace = null;
            workspaceFactory = new AccessWorkspaceFactoryClass();
            featureWorkspace = (IFeatureWorkspace)workspaceFactory.OpenFromFile(mdbFullPath, 0);
            return featureWorkspace;
        }

        /// <summary>
        /// 返回sde中的FeatureWorkspace
        /// </summary>
        /// <returns></returns>
        public static IFeatureWorkspace NewSdeFeatureWorkspace(string dbUserName, string dbPassword, string dbName, string servicer, string service)
        {

            //IFeatureWorkspace featureWorkspace = ExtensionMethods.NewSdeFeatureWorkspace("sa", "111111", "DySysDb", "PC-201203161034", "esri_sde");

            try
            {
                ESRI.ArcGIS.esriSystem.IPropertySet propertySet = new ESRI.ArcGIS.esriSystem.PropertySetClass();

                propertySet.SetProperty("SERVER", servicer);//服务器

                propertySet.SetProperty("INSTANCE", service);//服务

                propertySet.SetProperty("USER", dbUserName);

                propertySet.SetProperty("PASSWORD", dbPassword);

                propertySet.SetProperty("DATABASE", dbName);

                propertySet.SetProperty("VERSION", "SDE.DEFAULT");

                ESRI.ArcGIS.Geodatabase.IWorkspaceFactory factory = new ESRI.ArcGIS.DataSourcesGDB.SdeWorkspaceFactoryClass();

                IWorkspace ws = factory.Open(propertySet, 0);

                return (IFeatureWorkspace)ws;
            }
            catch (System.Exception ex)
            {
                Debug.Print("NewSdeFeatureWorkspace:" + ex.Message);
                return null;
            }

        }



        //创建mdb
        //IWorkspaceFactory workspaceFactory = new AccessWorkspaceFactory();
        //workspaceFactory.Create("文件夹路径", "数据库名，不用加mdb后缀", null, 0);


        #endregion


        #region FeatureClass


        //打开featureClass的新方法
        //IGPUtilities gsPUtilities = new GPUtilities();
        //gsPUtilities.OpenFeatureClassFromString();


        /// <summary>
        /// 根据shape路径，打开一个 已存在的FeatureClass 并返回IFeatureClass
        /// </summary>
        public IFeatureClass NewFeatureClass(string shapeFullPath)
        {
            IFeatureWorkspace featureWorkspace = this.NewShapeFeatureWorkspace(shapeFullPath);
            string shapeName = System.IO.Path.GetFileNameWithoutExtension(shapeFullPath);
            IFeatureClass featureClass = null;
            try
            {
                featureClass = featureWorkspace.OpenFeatureClass(shapeName);
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }

            return featureClass;
        }



        /// <summary>
        /// 搜索全部图层，看看map中是否已经加载了图层
        /// </summary>
        /// <param name="featureClass"></param>
        /// <returns></returns>
        public Boolean IsContainFeatureClass(IFeatureClass featureClass)
        {
            var allExistedFeatureClassPaths = this.AllExistedLayerList().Where(v => v.Valid).OfType<IFeatureLayer>().Cast<IFeatureLayer>()
                .Select(v => v.FeatureClass.GetFullPath());

            return allExistedFeatureClassPaths.Contains(featureClass.GetFullPath());
        }



        /// <summary>
        /// 创建featureclass（项目红线）,只有字段没有数据
        /// </summary>
        /// <returns></returns>
        public IFeatureClass CreateRedLineFeatureClass(String shapeFileFullPath)
        {
            IFeatureClassDescription featureClassDescription = new FeatureClassDescriptionClass();//为什么要这样
            IObjectClassDescription objectClassDescription = (IObjectClassDescription)featureClassDescription;
            
            IFields fields = objectClassDescription.RequiredFields;//必需的字段

            //获取shape字段的引用
            Int32 shapeFieldIndex = fields.FindField(featureClassDescription.ShapeFieldName);//获取shape字段的索引
            IField shapeField = fields.get_Field(shapeFieldIndex);
            //设置shape字段的类型和空间参考
            IGeometryDef geometryDef = shapeField.GeometryDef;
            IGeometryDefEdit geometryDefEdit = (IGeometryDefEdit)geometryDef;//编辑图形数据
            geometryDefEdit.GeometryType_2 = esriGeometryType.esriGeometryPolygon;//设置类型
            geometryDefEdit.SpatialReference_2 = MyAeMethods.Instance.GetSpatialReference_Xian1980_3_38();//设置空间参考

            // 这里只创建基本字段，不创建其他字段，如果是创建其他字段的话，则 IFieldChecker 
            // 就要用来执行字段名称的验证了
            // 如果什么字段都创建，则自动创建的字段有：FID(主键)、Shape,Id(Long)类型,
            // 只要你添加一个自己定义的字段，则Id字段会自动消失。

            IFieldsEdit fieldsEdit = (IFieldsEdit)fields;//编辑字段

            //添加自定义字段
            foreach (IField field in RedLineFieldInfo.Fields)
                fieldsEdit.AddField(field);


            String folderPath = System.IO.Path.GetDirectoryName(shapeFileFullPath);//文件夹路径
            String fileName = System.IO.Path.GetFileName(shapeFileFullPath);//文件名（含后缀）
            String featureClassName = System.IO.Path.GetFileNameWithoutExtension(shapeFileFullPath);//没后缀，用文件名作为featureClass的名称

            IFeatureWorkspace featureWorkspace = this.NewShapeFeatureWorkspace(shapeFileFullPath);//创建一个新的工作空间


            // 检查字段名称，如：shape文件不允许越长5个中文字长
            IFieldChecker fieldChecker = new FieldCheckerClass();
            IEnumFieldError enumFieldError;//用于收集错误
            IFields validatedFields;//经过验证的字段的集合

            fieldChecker.ValidateWorkspace = (IWorkspace)featureWorkspace;//设置工作空间
            fieldChecker.Validate(fields, out enumFieldError, out validatedFields);//开始验证

            if (null != enumFieldError)//如果有错误
            {
                //...
            }

            IFeatureClass featureClass = null;//待创建的featureClass

            //开始创建
            try
            {
                featureClass = featureWorkspace.CreateFeatureClass(
                    featureClassName,
                    validatedFields,//经过验证的字段的集合
                    objectClassDescription.InstanceCLSID,
                    objectClassDescription.ClassExtensionCLSID,
                    esriFeatureType.esriFTSimple,
                    featureClassDescription.ShapeFieldName,
                    String.Empty);
            }
            catch(COMException comEx)
            {
                MessageBox.Show(comEx.Message);
            }

            return featureClass;
        }



        //创建featureclass 自定义字段
        public IFeatureClass Create_custom_field_FeatureClass(String shapeFileFullPath, List<string> field_name_list)
        {
            //创建自定义字段
            List<IField> field_list = new List<IField>();
            foreach (var sdf in field_name_list)
            {
                IField field = new FieldClass();
                IFieldEdit2 fieldEdit = (IFieldEdit2)field;

                fieldEdit.Name_2 = sdf;//shape文件不能超过5个中文字，即10个字符
                fieldEdit.Type_2 = esriFieldType.esriFieldTypeDouble;
                fieldEdit.Length_2 = 20;
                fieldEdit.Precision_2 = 15;
                fieldEdit.DefaultValue_2 = 0;
                fieldEdit.Scale_2 = 5;//字段显示的宽度,double类型才设置？

                field_list.Add(field);
            }



            IFeatureClassDescription featureClassDescription = new FeatureClassDescriptionClass();//为什么要这样
            IObjectClassDescription objectClassDescription = (IObjectClassDescription)featureClassDescription;

            IFields fields = objectClassDescription.RequiredFields;//字段

            //获取shape字段的引用
            Int32 shapeFieldIndex = fields.FindField(featureClassDescription.ShapeFieldName);//获取shape字段的索引
            IField shapeField = fields.get_Field(shapeFieldIndex);
            //设置shape字段的类型和空间参考
            IGeometryDef geometryDef = shapeField.GeometryDef;
            IGeometryDefEdit geometryDefEdit = (IGeometryDefEdit)geometryDef;//编辑图形数据
            geometryDefEdit.GeometryType_2 = esriGeometryType.esriGeometryPolygon;//设置类型
            geometryDefEdit.SpatialReference_2 = MyAeMethods.Instance.GetSpatialReference_Xian1980_3_38();//设置空间参考

            // 这里只创建基本字段，不创建其他字段，如果是创建其他字段的话，则 IFieldChecker 
            // 就要用来执行字段名称的验证了
            // 如果什么字段都创建，则自动创建的字段有：FID(主键)、Shape,Id(Long)类型,
            // 只要你添加一个自己定义的字段，则Id字段会自动消失。

            IFieldsEdit fieldsEdit = (IFieldsEdit)fields;//编辑字段

            //添加自定义字段
            foreach (IField field in field_list)
                fieldsEdit.AddField(field);


            String folderPath = System.IO.Path.GetDirectoryName(shapeFileFullPath);//文件夹路径
            String fileName = System.IO.Path.GetFileName(shapeFileFullPath);//文件名（含后缀）
            String featureClassName = System.IO.Path.GetFileNameWithoutExtension(shapeFileFullPath);//没后缀，用文件名作为featureClass的名称

            IFeatureWorkspace featureWorkspace = this.NewShapeFeatureWorkspace(shapeFileFullPath);//创建一个新的工作空间


            // 检查字段名称，如：shape文件不允许越长5个中文字长
            IFieldChecker fieldChecker = new FieldCheckerClass();
            IEnumFieldError enumFieldError;//用于收集错误
            IFields validatedFields;//经过验证的字段的集合

            fieldChecker.ValidateWorkspace = (IWorkspace)featureWorkspace;//设置工作空间
            fieldChecker.Validate(fields, out enumFieldError, out validatedFields);//开始验证

            if (null != enumFieldError)//如果有错误
            {
                //...
            }

            IFeatureClass featureClass = null;//待创建的featureClass

            //开始创建
            try
            {
                featureClass = featureWorkspace.CreateFeatureClass(
                    featureClassName,
                    validatedFields,//经过验证的字段的集合
                    objectClassDescription.InstanceCLSID,
                    objectClassDescription.ClassExtensionCLSID,
                    esriFeatureType.esriFTSimple,
                    featureClassDescription.ShapeFieldName,
                    String.Empty);
            }
            catch (COMException comEx)
            {
                MessageBox.Show(comEx.Message);
            }

            return featureClass;
        }


        /// <summary>
        /// 往FeatureClass中添加一条数据
        /// </summary>
        /// <param name="FeatureClass"></param>
        /// <param name="redLineRowInfo"></param>
        /// <returns></returns>
        public Boolean AddDataToFeatureClass(IFeatureClass featureClass, RedLineRowInfo redLineRowInfo)
        {
            return AddDatasToFeatureClass(featureClass, new RedLineRowInfo[] { redLineRowInfo });
        }


        /// <summary>
        /// 往FeatureClass中添加一系列数据：创建项目红线、批次用地
        /// </summary>
        /// <param name="FeatureClass"></param>
        /// <param name="redLineRowInfo"></param>
        /// <returns></returns>
        public Boolean AddDatasToFeatureClass(IFeatureClass featureClass, IEnumerable<RedLineRowInfo> redLineRowInfos)
        {
            int i = 0;

            if (null == featureClass)
                return false;

            //检查featureclass的字段是否符合要求（有必要吗，字段前面用代码创建，中间没什么可能在不知情的情况下更改）
            //.....

            IFields fields = featureClass.Fields;

            //获取featureclass各字段的索引，地类编码字段呢？
            Int32 indexNumberOfPoints = fields.FindField(Constants.NUMBER_OF_POINT_FIELD_NAME); // 1
            Int32 indexBlockArea = fields.FindField(Constants.AREA_FIELD_NAME); // 2
            Int32 indexBlockId = fields.FindField(Constants.BLOCK_ID_FIELD_NAME); // 3
            Int32 indexBlockName = fields.FindField(Constants.BLOCK_NAME_FIELD_NAME); // 4
            Int32 indexBlockGeometryType = fields.FindField(Constants.GEOMETRY_TYPE_FIELD_NAME); // 5
            Int32 indexUsage = fields.FindField(Constants.USAGE_FIELD_NAME); // 6
            Int32 indexPageNum = fields.FindField(Constants.PAGE_NUM_FIELD_NAME); // 7
            Int32 indexRemark = fields.FindField(Constants.REMARK_FIELD_NAME); // 8

            //写入数据
            IFeatureCursor addFeatureCursor = null;

            foreach (RedLineRowInfo redLineRowInfo in redLineRowInfos)
            {
                i++;

                IFeatureBuffer featureBuffer = featureClass.CreateFeatureBuffer();

                featureBuffer.set_Value(indexNumberOfPoints, redLineRowInfo.NumberOfPoint);
                featureBuffer.set_Value(indexBlockArea, redLineRowInfo.BlockArea);
                featureBuffer.set_Value(indexBlockId, redLineRowInfo.BlockId);
                featureBuffer.set_Value(indexBlockName, redLineRowInfo.BlockName);
                featureBuffer.set_Value(indexBlockGeometryType, redLineRowInfo.BlockGeometryType);
                featureBuffer.set_Value(indexUsage, redLineRowInfo.LandUsage);
                featureBuffer.set_Value(indexPageNum, redLineRowInfo.PageNum);
                featureBuffer.set_Value(indexRemark, redLineRowInfo.Remark);
                featureBuffer.Shape = redLineRowInfo.Polygon;

                Boolean isAddSuccess = false;//标记插入的成功与否

                try
                {
                    addFeatureCursor = featureClass.Insert(true);//true：使用buffer
                    addFeatureCursor.InsertFeature(featureBuffer);
                    addFeatureCursor.Flush();//刷新
                    isAddSuccess = true;
                    Debug.Print(string.Format("AddDatasToFeatureClass：添加第{0}条记录成功，共{1}条记录。", i.ToString(), redLineRowInfos.Count().ToString()));
                }
                catch
                {
                    isAddSuccess = false;
                    Debug.Print(string.Format("！！AddDatasToFeatureClass：添加第{0}条记录失败，共{1}条记录。", i.ToString(), redLineRowInfos.Count().ToString()));
                }
                finally
                {
                    if (null != addFeatureCursor)
                        Marshal.ReleaseComObject(addFeatureCursor);
                }

                if (isAddSuccess == false)
                    return false;

            }

            return true;
        }



        /// <summary>
        /// 往featureClass中添加数据（自定义字段，字段值默认）
        /// </summary>
        /// <param name="featureClass"></param>
        /// <param name="redLineRowInfos"></param>
        /// <returns></returns>
        public Boolean AddDatasToFeatureClass(IFeatureClass featureClass,List<string> field_name_list,List<IPolygon> polygon_list )
        {
            int i = 0;

            if (null == featureClass)
                return false;

            //检查featureclass的字段是否符合要求（有必要吗，字段前面用代码创建，中间没什么可能在不知情的情况下更改）
            //.....

            IFields fields = featureClass.Fields;

            /*//获取featureclass各字段的索引，地类编码字段呢？
            Int32 indexNumberOfPoints = fields.FindField(Constants.NUMBER_OF_POINT_FIELD_NAME); // 1
            Int32 indexBlockArea = fields.FindField(Constants.AREA_FIELD_NAME); // 2
            Int32 indexBlockId = fields.FindField(Constants.BLOCK_ID_FIELD_NAME); // 3
            Int32 indexBlockName = fields.FindField(Constants.BLOCK_NAME_FIELD_NAME); // 4
            Int32 indexBlockGeometryType = fields.FindField(Constants.GEOMETRY_TYPE_FIELD_NAME); // 5
            Int32 indexUsage = fields.FindField(Constants.USAGE_FIELD_NAME); // 6
            Int32 indexPageNum = fields.FindField(Constants.PAGE_NUM_FIELD_NAME); // 7
            Int32 indexRemark = fields.FindField(Constants.REMARK_FIELD_NAME); // 8*/

            //写入数据
            IFeatureCursor addFeatureCursor = null;

            foreach (var sdsd in polygon_list)
            {
                i++;

                IFeatureBuffer featureBuffer = featureClass.CreateFeatureBuffer();

                /*featureBuffer.set_Value(indexNumberOfPoints, redLineRowInfo.NumberOfPoint);
                featureBuffer.set_Value(indexBlockArea, redLineRowInfo.BlockArea);
                featureBuffer.set_Value(indexBlockId, redLineRowInfo.BlockId);
                featureBuffer.set_Value(indexBlockName, redLineRowInfo.BlockName);
                featureBuffer.set_Value(indexBlockGeometryType, redLineRowInfo.BlockGeometryType);
                featureBuffer.set_Value(indexUsage, redLineRowInfo.LandUsage);
                featureBuffer.set_Value(indexPageNum, redLineRowInfo.PageNum);
                featureBuffer.set_Value(indexRemark, redLineRowInfo.Remark);*/

                foreach (var yyu in field_name_list)
                {
                    featureBuffer.set_Value(fields.FindField(yyu), 0);
                }


                featureBuffer.Shape = sdsd;

                Boolean isAddSuccess = false;//标记插入的成功与否

                try
                {
                    addFeatureCursor = featureClass.Insert(true);//true：使用buffer
                    addFeatureCursor.InsertFeature(featureBuffer);
                    addFeatureCursor.Flush();//刷新
                    isAddSuccess = true;
                    Debug.Print(string.Format("AddDatasToFeatureClass：添加第{0}条记录成功，共{1}条记录。", i.ToString(), polygon_list.Count.ToString()));
                }
                catch
                {
                    isAddSuccess = false;
                    Debug.Print(string.Format("！！AddDatasToFeatureClass：添加第{0}条记录失败，共{1}条记录。", i.ToString(), polygon_list.Count.ToString()));
                }
                finally
                {
                    if (null != addFeatureCursor)
                        Marshal.ReleaseComObject(addFeatureCursor);
                }

                if (isAddSuccess == false)
                    return false;

            }

            return true;
        }


        #endregion


        #region FeatureCursor
        /// <summary>
        /// 创建一个 FeatureCursor
        /// </summary>
        /// <param name="featureClass">要素类</param>
        /// <param name="whereColumn">条件语句(相当于sql语句的where)</param>
        /// <param name="subFields">要显示的字段(//相当于sql语句的select from xxxx)</param>
        /// <returns></returns>
        public IFeatureCursor NewFeatureCursor(IFeatureClass featureClass, string whereClause, string subFields)
        {
            IQueryFilter queryFilter = new QueryFilterClass();//查询过滤器
            IFeatureCursor featureCursor = null;//要素光标
            queryFilter.WhereClause = whereClause;//注意mdb和shp的格式不一样（具体在ArcMap上测试），mdb： "[字段名] = '字段值'"    shp： "\"字段名\" = '字段值'"
            queryFilter.SubFields = subFields;
            featureCursor = featureClass.Search(queryFilter, true);//true：传引用
            return featureCursor;
        }


        //如果用IFeatureCursor插入多条记录时，出现“不能在打开多条记录了”，要先释放游标
        /*IFeatureCursor insertFeatureCursor = totalFeatureClass.Insert(true);
        insertFeatureCursor.InsertFeature(featureBuffer);
        insertFeatureCursor.Flush();
        System.Runtime.InteropServices.Marshal.ReleaseComObject(insertFeatureCursor);*/

        #endregion


        #region layer

        /// <summary>
        /// 根据shape路径，并返回IFeatureLayer
        /// </summary>
        /// <param name="shapeFullPath"></param>
        /// <returns></returns>
        public IFeatureLayer NewFeatureLayer(string shapeFullPath)
        {
            IFeatureClass featureClass = this.NewFeatureClass(shapeFullPath);
            IFeatureLayer featureLayer = new FeatureLayerClass();
            featureLayer.FeatureClass = featureClass;
            featureLayer.Name = featureClass.AliasName;
            return featureLayer;
        }



        /// <summary>
        /// 创建一个以默认样式上色的的项目红线图层（无填充颜色，边线为红色）
        /// </summary>
        /// <param name="featureclass"></param>
        /// <returns></returns>
        public IFeatureLayer NewRedFeatureLayer(IFeatureClass redFeatureclass)
        {
            if (null == redFeatureclass)
                return null;

            IFeatureLayer redFeatureLayer = new FeatureLayerClass();
            redFeatureLayer.FeatureClass = redFeatureclass;
            redFeatureLayer.Name = redFeatureclass.AliasName;

            IGeoFeatureLayer geoFeatureLayer = (IGeoFeatureLayer)redFeatureLayer;
            geoFeatureLayer.Renderer = this.NewRedFeatureLayerRenderer();

            return redFeatureLayer;
        }


        /// <summary>
        /// 获取当前焦点地图的所有图层列表集合
        /// </summary>
        /// <returns></returns>
        public List<ILayer> AllExistedLayerList()
        {
            List<ILayer> layerList = new List<ILayer>();
            IMap focusMap=MapAndPageSync.Instance.FocusMap;

            for (int i = 0; i < focusMap.LayerCount; i++)
                layerList.Add(focusMap.get_Layer(i));

            return layerList;
        }


        /// <summary>
        /// 系统要求图层名必须唯一，此函数检查图层名的正确性，并返回唯一性的图层名
        /// </summary>
        /// <param name="currentLayerName">将要添加的图层名</param>
        /// <param name="newLayerName">检验后的图层名，必须唯一</param>
        public void ValidateLayerName(String currentLayerName,ref String newLayerName)
        {
            if (String.IsNullOrEmpty(currentLayerName.Trim()))//如果为空
                currentLayerName = "无名称";

            //所有在map上的图层名
            var allExistedLayerName = AllExistedLayerList().Select(v => v.Name).ToList();

            if (!allExistedLayerName.Contains(currentLayerName))//如果不包含
                newLayerName = currentLayerName;
            else
            {
                Int32 count = 1;

                while (true)
                {
                    String tempName = currentLayerName + "_" + count.ToString();

                    if (!allExistedLayerName.Contains(tempName))
                    {
                        newLayerName = tempName;
                        break;
                    }

                    count++;
                }
            }
        }
        #endregion


        #region 删除、添加图层

        /// <summary>
        /// 删除一个图层
        /// </summary>
        /// <param name="layer"></param>
        public void DeleteLayer(ILayer layer)
        {
            DeleteLayers(new ILayer[] { layer });
        }


        /// <summary>
        /// 删除一系列图层
        /// </summary>
        /// <param name="layers"></param>
        public void DeleteLayers(IEnumerable<ILayer> layers)
        {
            List<ILayer> removedlayersList = new List<ILayer>();//将已经删除的图层，添加进list
            IMap focusMap = MapAndPageSync.Instance.FocusMap;

            foreach (var layer in layers)
            {
                if (null != LayerChanging)
                {
                    var e = new LayerChangingEventArgs(layer, LayerAction.Remove);
                    LayerChanging(this, e);
                    if (e.Cancel)
                        continue;
                }
                focusMap.DeleteLayer(layer);
                removedlayersList.Add(layer);
            }

            // 如果有删除，则刷新
            if (removedlayersList.Count > 0)
            {
                ((IActiveView)focusMap).PartialRefresh(esriViewDrawPhase.esriViewForeground, null, null);
                if (null != LayerChanged)
                {
                    LayerChanged.Invoke(this, new LayerChangedEventArgs(removedlayersList, LayerAction.Remove));
                }
            }
        }



        /// <summary>
        /// 添加一个图层
        /// </summary>
        /// <param name="layer"></param>
        public void AddLayer(ILayer layer)
        {
            AddLayers(new EnumLayerClass(layer), true);
        }



        /// <summary>
        /// 添加一系列图层
        /// </summary>
        public void AddLayers(IEnumLayer enumLayer, Boolean autoArrange)
        {
            IMap focusMap = MapAndPageSync.Instance.FocusMap;
            ////当前地图窗口已以有的图层名称的列表
            List<String> existedLayerNameList = AllExistedLayerList().Select(v => v.Name).ToList();
            //保存待添加图层的集合
            //IEnumLayer toAddLayers = new EnumLayerClass();//不能这样
            EnumLayerClass toAddLayers = new EnumLayerClass();

            enumLayer.Reset();

            #region 检查图层的名称是否唯一
            try
            {
                ILayer currentLayer = enumLayer.Next();
                while (null != currentLayer)
                {
                    if (null != LayerChanging)
                    {
                        var e = new LayerChangingEventArgs(currentLayer, LayerAction.Add);
                        LayerChanging(this, e);

                        if (e.Cancel)
                        {
                            currentLayer = enumLayer.Next();
                            continue;
                        }
                    }

                    String newLayerName = String.Empty;
                    //检查图层是是否重复，如果重复重命名
                    this.ValidateLayerName(currentLayer.Name, ref newLayerName);

                    currentLayer.Name = newLayerName;//新的图层名

                    existedLayerNameList.Add(newLayerName);
                    toAddLayers.AddLayerToList(currentLayer);

                    currentLayer = enumLayer.Next();//下一个图层
                }
            }
            catch // 使用Next方法时必须添加异常处理。
            {
                //MessageBox.Show(ex.ToString(),"检查图层名");
                //这里会出现异常，不要show出来，不妨碍后面的添加图层
            }
            #endregion

            // 如果没有要处理的图层，则无返回了
            if (toAddLayers.LayerCount <= 0)
                return;

            toAddLayers.Reset();

            try
            {
                focusMap.AddLayers(toAddLayers, autoArrange);//添加一系列图层
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "focusMap.AddLayers出错");
            }

            //局部刷新
            MapAndPageSync.Instance.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, null);

            // 必须调用些方法，否则图层管理不会更新
            MapAndPageSync.Instance.TOCControl.Update();

            // 通知 LayerChanged 事件的订阅者，事件已以发生
            if (null != LayerChanged)
                LayerChanged(this, new LayerChangedEventArgs(toAddLayers.LayerList, LayerAction.Add));

        }

        #endregion


        #region Renderer 渲染图层
        /// <summary>
        /// (简单渲染)创建一个红线填充样式（无填充颜色，边线为红色）
        /// </summary>
        /// <returns></returns>
        public IFeatureRenderer NewRedFeatureLayerRenderer()
        {
            //边线颜色，红色
            IRgbColor rgbColor = new RgbColorClass();
            rgbColor.Red = 255;
            rgbColor.Green = 0;
            rgbColor.Blue = 0;

            //填充颜色，唔、无
            IColor nullColor = new RgbColorClass();
            nullColor.NullColor = true;

            //边线样式
            ILineSymbol lineSymbol = new SimpleLineSymbolClass();
            lineSymbol.Color = rgbColor;
            lineSymbol.Width = 1.2;

            //填充样式
            IFillSymbol fillSymbol = new SimpleFillSymbolClass();
            fillSymbol.Outline = lineSymbol;//边线
            fillSymbol.Color = nullColor;//内部填充
            //fillSymbol.Color.NullColor = true; // 直接设置不会产生效果！

            var simpleRenderer = new SimpleRendererClass();
            simpleRenderer.Symbol = (ISymbol)fillSymbol;
            //simpleRenderer.Symbol = (ISymbol)lineSymbol;

            return (IFeatureRenderer)simpleRenderer;
        }


        /// <summary>
        /// (独立值渲染)（无填充颜色，边线为红色）
        /// </summary>
        /// <returns></returns>
        public IFeatureRenderer NewUniqueRenderer()
        {
            //边线颜色，红色
            IRgbColor rgbColor = new RgbColorClass();
            rgbColor.Red = 255;
            rgbColor.Green = 0;
            rgbColor.Blue = 0;

            //填充颜色，唔、无
            IColor nullColor = new RgbColorClass();
            nullColor.NullColor = true;

            //边线样式
            ILineSymbol lineSymbol = new SimpleLineSymbolClass();
            lineSymbol.Color = rgbColor;
            lineSymbol.Width = 1.2;


            //填充样式
            IFillSymbol fillSymbol = new SimpleFillSymbolClass();
            fillSymbol.Outline = lineSymbol;//边线
            fillSymbol.Color = nullColor;//内部填充
            //fillSymbol.Color.NullColor = true; // 直接设置不会产生效果！

            IUniqueValueRenderer uniqueValueRenderer = new UniqueValueRendererClass();
            uniqueValueRenderer.FieldCount = 1;//这个一定要有，要渲染的字段数
            uniqueValueRenderer.set_Field(0, "权属单位名");//这个一定要有，要渲染的字段名
            //根据字段值渲染
            uniqueValueRenderer.AddValue("洋里村委会、红光村翻身屋、五更屋经济合作社共有", "权属单位名", (ISymbol)fillSymbol);// 字段值 字段名

            return (IFeatureRenderer)uniqueValueRenderer;


        }


        /// <summary>
        /// 为点图层添加2种样式
        /// </summary>
        public void AddTwoStyleToPointLayer(IGeoFeatureLayer geoFeatureLayer_point)
        {
            //设置Symbol Property Editor,ArcMap-->单击点图层的样式-->点击preview里面的样式

            //第一种样式
            ICharacterMarkerSymbol characterMarkerSymbol1 = new CharacterMarkerSymbolClass();
            StdFont stdFont1 = new StdFont();
            stdFont1.Name = "ESRI Default Marker";//Character Marker面板-->Font
            stdFont1.Size = 2;//Mask面板-->Size
            characterMarkerSymbol1.Font = (IFontDisp)stdFont1;
            characterMarkerSymbol1.CharacterIndex = 33;//Character Marker面板-->Unicode
            characterMarkerSymbol1.Size = 8;//Character Marker面板-->Size
            IRgbColor rgbColor_point = new RgbColorClass();
            rgbColor_point.Red = 255;
            rgbColor_point.Green = 255;
            rgbColor_point.Blue = 255;
            characterMarkerSymbol1.Color = rgbColor_point;

            //第二种样式
            ICharacterMarkerSymbol characterMarkerSymbol2 = new CharacterMarkerSymbolClass();
            StdFont stdFont2 = new StdFont();
            stdFont2.Name = "ESRI Default Marker";//一定要设置这个
            stdFont2.Size = 2;
            characterMarkerSymbol2.Font = (IFontDisp)stdFont2;
            characterMarkerSymbol2.CharacterIndex = 46;
            characterMarkerSymbol2.Size = 8;
            IRgbColor rgbColor_point2 = new RgbColorClass();
            rgbColor_point2.Red = 255;
            rgbColor_point2.Green = 0;
            rgbColor_point2.Blue = 0;
            characterMarkerSymbol2.Color = rgbColor_point2;

            IMultiLayerMarkerSymbol multiLayerMarkerSymbol = new MultiLayerMarkerSymbolClass();
            multiLayerMarkerSymbol.AddLayer(characterMarkerSymbol1);
            multiLayerMarkerSymbol.AddLayer(characterMarkerSymbol2);

            var simpleRenderer_point = new SimpleRendererClass();
            simpleRenderer_point.Symbol = (ISymbol)multiLayerMarkerSymbol;
            geoFeatureLayer_point.Renderer = (IFeatureRenderer)simpleRenderer_point;
        }

        #endregion


        #region 图层的label

        /// <summary>
        /// 用不同的类设置图层的label（arcMap-->图层属性-->label-->勾选Lable feature in this layers-->method选第二个）
        /// </summary>
        /// <param name="geoFeatureLayer">要设置label的图层</param>
        /// <param name="fieldName_qsdwm">要演示字段的名称</param>
        /// <param name="fieldName_qsdwm">要演示字段的那一列的值</param>
        public void SetLable_InTwoClass(IGeoFeatureLayer geoFeatureLayer, string fieldName_qsdwm, string qsdwm)
        {
            IAnnotateLayerPropertiesCollection annotateLayerPropertiesCollection = (IAnnotateLayerPropertiesCollection)geoFeatureLayer.AnnotationProperties;
            //annotateLayerPropertiesCollection.Clear();//先清除所有的类

            #region 标注类一
            //过滤的条件，即符合条件的才会应该该标注类的样式
            string whereStr_label_style_1 = string.Format("\"{0}\" <> '{1}'", fieldName_qsdwm, qsdwm);//mdb： "[字段名] = '字段值'"    shp： "\"字段名\" = '字段值'"
            IAnnotateLayerProperties annotateLayerProperties_1 = null;
            IElementCollection poly_placedElements = null;
            IElementCollection poly_unplacedElements = null;
            //获取default类的实例,注意QueryItem(0,,,,),即获取第一个类
            annotateLayerPropertiesCollection.QueryItem(0, out annotateLayerProperties_1, out poly_placedElements, out poly_unplacedElements);
            annotateLayerProperties_1.WhereClause = whereStr_label_style_1;
            annotateLayerProperties_1.DisplayAnnotation = true;


            // 设置标注的样式
            IRgbColor rgbColor_1 = new RgbColorClass();
            rgbColor_1.Red = 0;
            rgbColor_1.Green = 0;
            rgbColor_1.Blue = 255;
            ITextSymbol textSymbol_1 = new TextSymbolClass();
            textSymbol_1.Size = 8;
            textSymbol_1.Font.Name = "新宋体";
            textSymbol_1.Color = rgbColor_1;

            //设置显示哪些字段作为标注
            ILabelEngineLayerProperties2 labelEngineLayerProperties_1 = (ILabelEngineLayerProperties2)annotateLayerProperties_1;
            labelEngineLayerProperties_1.IsExpressionSimple = true;//是否简单表达
            labelEngineLayerProperties_1.Expression = string.Format("[{0}]", fieldName_qsdwm);//在图上显示的字段  //注意这里  [xxx]
            labelEngineLayerProperties_1.Symbol = textSymbol_1;
            #endregion


            #region 标注类二
            //过滤的条件，即符合条件的才会应该该标注类的样式
            string whereStr_label_style_2 = string.Format("\"{0}\" = '{1}'", fieldName_qsdwm, qsdwm);//mdb： "[字段名] = '字段值'"    shp： "\"字段名\" = '字段值'"
            //创建一个新的标注类
            IAnnotateLayerProperties annotateLayerProperties_2 = new LabelEngineLayerPropertiesClass();
            annotateLayerProperties_2.Class = "label_2";//类名
            annotateLayerProperties_2.FeatureLayer = geoFeatureLayer;
            annotateLayerProperties_2.WhereClause = whereStr_label_style_2;
            annotateLayerProperties_2.DisplayAnnotation = true;

            // 设置标注的样式
            IRgbColor rgbColor_2 = new RgbColorClass();
            rgbColor_2.Red = 255;
            rgbColor_2.Green = 0;
            rgbColor_2.Blue = 0;
            ITextSymbol textSymbol_2 = new TextSymbolClass();
            textSymbol_2.Size = 8;
            textSymbol_2.Font.Name = "新宋体";
            textSymbol_2.Color = rgbColor_2;

            //设置显示哪些字段作为标注
            IAnnotationExpressionEngine annotationExpressionEngine = new AnnotationJScriptEngine();
            //javascript 代码（默认是vb6代码，用IAnnotationExpressionEngine可以改用javascript代码，代码中\r是换行）
            var strCode = "function FindLabel ( [地籍号],[权属单位名] ,[宗地面积]  ){var p = [权属单位名] + \"\\r\" +  [地籍号] + \"\\r\" + (parseFloat([宗地面积]/10000)).toFixed(4).toString()  ;return p;}";
            annotationExpressionEngine.SetCode(strCode, "FindLabel");//注意设置函数名

            ILabelEngineLayerProperties2 labelEngineLayerProperties_2 = (ILabelEngineLayerProperties2)annotateLayerProperties_2;
            labelEngineLayerProperties_2.IsExpressionSimple = false;//注意这里是false //是否简单表达
            labelEngineLayerProperties_2.ExpressionParser = annotationExpressionEngine;
            labelEngineLayerProperties_2.Expression = strCode;//在图上显示的字段  //注意这里  [xxx]
            labelEngineLayerProperties_2.Symbol = textSymbol_2;

            annotateLayerPropertiesCollection.Add(annotateLayerProperties_2);
            #endregion

            geoFeatureLayer.DisplayAnnotation = true;

        }

        #endregion


        #region mxd

        //IMapDocument要用到
        [DllImport("user32.dll")]
        static extern IntPtr GetDesktopWindow();

        /// <summary>
        /// 打开mxd文档
        /// </summary>
        /// <param name="mxdFullPath"></param>
        public void OpenMxdDoc(string mxdFullPath,IMapControl3 mapCtrl,IPageLayoutControl2 pageCtrl)
        {
            mapCtrl.LoadMxFile(mxdFullPath, null, string.Empty);
            pageCtrl.LoadMxFile(mxdFullPath, string.Empty);
        }

        //怎样用后台的方式操作mxd文档，用IMapDocument
        /*
        IMapDocument mapDocument = new MapDocumentClass();
        mapDocument.Open(mdbFullPath, string.Empty);//打开mxd
        mapDocument.ActiveView.FocusMap.AddLayers(enumLayerClass, true);//添加图层
        //这里一定要Activate
        ((IActiveView)(mapDocument.get_Map(0))).Activate(GetDesktopWindow().ToInt32());
        ((IActiveView)mapDocument.PageLayout).Activate(GetDesktopWindow().ToInt32());
        ((IActiveView)mapDocument.PageLayout).Refresh();//记得刷新
        mapDocument.SaveAs(mxd_path, false, false);//另存为mxd
        mapDocument.Close();//关闭
        */
        #endregion


        #region 设置鼠标样式
        /// <summary>
        /// 设置为忙状态（设置鼠标为漏斗形状）
        /// </summary>
        public void SetBusyState()
        {
            _mainForm.Cursor = Cursors.WaitCursor;
            _mapControl.MousePointer = esriControlsMousePointer.esriPointerHourglass;
            _pageLayoutControl.MousePointer = esriControlsMousePointer.esriPointerHourglass;
            _tocControl.MousePointer = esriControlsMousePointer.esriPointerHourglass;
            _toolbarControl.MousePointer = esriControlsMousePointer.esriPointerHourglass;

            _mapControl.Enabled = false;
            _pageLayoutControl.Enabled = false;
            _tocControl.Enabled = false;
            _toolbarControl.Enabled = false;
        }


        /// <summary>
        /// 设置鼠标为默认形状
        /// </summary>
        public void SetDefaultState()
        {
            _mainForm.Cursor = Cursors.Default;
            _mapControl.MousePointer = esriControlsMousePointer.esriPointerDefault;
            _pageLayoutControl.MousePointer = esriControlsMousePointer.esriPointerDefault;
            _tocControl.MousePointer = esriControlsMousePointer.esriPointerDefault;
            _toolbarControl.MousePointer = esriControlsMousePointer.esriPointerDefault;

            _mapControl.Enabled = true;
            _pageLayoutControl.Enabled = true;
            _tocControl.Enabled = true;
            _toolbarControl.Enabled = true;
        }

        #endregion


        #region 导出jpg
        /// <summary>
        /// 导出jpg,输出全图的话，第二个参数要是fullExtent，且最后一个参数isFullExtent = true
        /// </summary>
        /// <param name="activeView"></param>
        /// <param name="envelope"></param>
        /// <param name="resolution">96,150,200,300,400</param>
        /// <param name="jpgFilePath">是否导出全图(注意全图的概念，pageLayout的全图指的是整个pageLayout界面，map的全图指的是整个地图的fullExtent)</param>
        public void ExportJpg(
            IActiveView activeView,
            IEnvelope envelope,
            Int32 resolution,
            String jpgFilePath,
            Boolean isFullExtent)
        {
            Double screenResolution = 96;
            Double ratio = resolution / screenResolution;

            if (resolution < 10)
            {
                MessageBox.Show("分辨率必需大于10","导出jpg",MessageBoxButtons.OK,MessageBoxIcon.Stop);
                return;
            }

            if (System.IO.File.Exists(jpgFilePath))//如果存在jpg文件,删除
            {
                try
                {
                    System.IO.File.Delete(jpgFilePath);
                }
                catch(Exception ex)
                {
                    MessageBox.Show("删除jpg文件失败！" + Environment.NewLine + ex.Message,"导出jpg");
                    return;
                }
            }

            IExport exportJPG = new ExportJPEGClass();

            #region 生成PixelBounds
            IDisplayTransformation displayTransformation = activeView.ScreenDisplay.DisplayTransformation;

            tagRECT deviceRect = new tagRECT();
            tagRECT exportRect = new tagRECT();

            IEnvelope pixelBound = new EnvelopeClass();

            //根据要导出的范围（包络线），生成tagRECT，即devRect
            //将要导出的范围转换为设备。。
            displayTransformation.TransformRect(envelope, ref deviceRect, (Int32)esriDisplayTransformationEnum.esriTransformToDevice);

            exportRect.left = exportRect.top = 0;

            // 下面之后以不直接使用 devRect.right *resolution / screenResolutio，是因为，经测试
            // devRect.left 的值有可能为负或正，不一定就是0
            exportRect.right = (Int32)Math.Ceiling((deviceRect.right - deviceRect.left) * ratio);
            exportRect.bottom = (Int32)Math.Ceiling((deviceRect.bottom - deviceRect.top) * ratio);

            /**
             * 以于PageLayout视图，当导出FullExtent时，就是导出页面视图，这种情况下
             * 不能用IActiveView.FullExtent来获得要导出的范围，而是应该通过IActiveView.ExportFrame 来
             * 直接获得一个tagRect结构
             */
            if (isFullExtent && !(activeView is Map))
            {
                exportRect.right = (Int32)Math.Ceiling(activeView.ExportFrame.right * ratio);
                exportRect.bottom = (Int32)Math.Ceiling(activeView.ExportFrame.bottom * ratio);
            }

            //生成一个新的包络线
            pixelBound.PutCoords(exportRect.left, exportRect.top, exportRect.right, exportRect.bottom);
            #endregion

            exportJPG.ExportFileName = jpgFilePath;
            exportJPG.Resolution = resolution;
            exportJPG.PixelBounds = pixelBound;

            bool export_success = false;//标记为导出失败
            try
            {
                Int32 hDC = exportJPG.StartExporting();
                activeView.Output(hDC, (Int16)exportJPG.Resolution, ref exportRect, isFullExtent ? null : envelope, null);
                exportJPG.FinishExporting();
                exportJPG.Cleanup();
                export_success = true;
            }
            catch(COMException comEX)
            {
                MessageBox.Show("导出jpg时遇到错误，请重试！" + comEX.Message);
            }

            // 打开jpg
            if (export_success && MessageBox.Show("地图已输出到：\n" + jpgFilePath + "是否立即打开？", "导出jpg", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK)
            {
                //Process process = new Process();
                //process.StartInfo.FileName = jpgFilePath;
                //process.Start();
                MyMethods.startProcess(jpgFilePath);
            }
        }


        #endregion


        #region 几何图形(polygon envelop)
        /// <summary>
        /// 将Envelop类型转换为PolygonClass(注意坐标系)
        /// </summary>
        /// <param name="envelop"></param>
        /// <returns></returns>
        public PolygonClass EnvelopToPolygonClass(IEnvelope envelop, ISpatialReference spatialReference)
        {
            PolygonClass polygon = new PolygonClass();
            System.Object missing = Type.Missing;//不可以直接转换为IPolygon吗？

            polygon.SpatialReference = spatialReference;

            polygon.AddPoint(envelop.LowerLeft, ref missing, ref missing);//左下角
            polygon.AddPoint(envelop.UpperLeft, ref missing, ref missing);//左上角
            polygon.AddPoint(envelop.UpperRight, ref missing, ref missing);//右上角
            polygon.AddPoint(envelop.LowerRight, ref missing, ref missing);//右下角
            polygon.AddPoint(envelop.LowerLeft, ref missing, ref missing);//再左下角

            return polygon;
        }


        /// <summary>
        /// 合并featureClss中的每条多边形记录
        /// </summary>
        /// <returns>返回实现IPolygon的类</returns>
        public IPolygon UnionPolygons(IFeatureClass featureClass)
        {
            IGeoDataset pGeoDataset = (IGeoDataset)featureClass;
            //GeometryBagClass：An ordered collection of objects that support the IGeometry interface
            IGeometry geometryBag = new GeometryBagClass();
            geometryBag.SpatialReference = pGeoDataset.SpatialReference;//定义geometryBag坐标参考
            IGeometryCollection pGeometryCollection = (IGeometryCollection)geometryBag;
            //遍历项目红线要素图层中每一个要素，null指没有条件
            IFeatureCursor pFeatureCursor = featureClass.Search(null, false);
            IFeature pFeature = null;//存放项目红线要素图层中每一个要素
            //下一个要素数据，featureCursor初始状态不指向任何要素
            pFeature = pFeatureCursor.NextFeature();
            while (pFeature != null)
            {
                object missing = Type.Missing;
                //将每个要素放进geometryCollection，相当于放进geometryBag
                pGeometryCollection.AddGeometry(pFeature.Shape, ref missing, ref missing);
                pFeature = pFeatureCursor.NextFeature();
            }
            //PolygonClass实现ITopologicalOperator接口
            ITopologicalOperator pTopologicalOperator = new PolygonClass();
            pTopologicalOperator.ConstructUnion((IEnumGeometry)geometryBag);
            IPolygon resultPolygon = (IPolygon)pTopologicalOperator;
            return resultPolygon;
        }


        /// <summary>
        /// 合并list feature中的每条多边形记录
        /// </summary>
        /// <returns>返回实现IPolygon的类</returns>
        public IPolygon UnionPolygons(ISpatialReference spatialReference, List<IFeature> featureList)
        {
            //IGeoDataset pGeoDataset = (IGeoDataset)featureClass;
            //GeometryBagClass：An ordered collection of objects that support the IGeometry interface
            IGeometry geometryBag = new GeometryBagClass();
            geometryBag.SpatialReference = spatialReference;//定义geometryBag坐标参考
            IGeometryCollection pGeometryCollection = (IGeometryCollection)geometryBag;

            foreach (var pFeature in featureList)
            {
                object missing = Type.Missing;
                //将每个要素放进geometryCollection，相当于放进geometryBag
                pGeometryCollection.AddGeometry(pFeature.Shape, ref missing, ref missing);
            }
            //PolygonClass实现ITopologicalOperator接口
            ITopologicalOperator pTopologicalOperator = new PolygonClass();
            pTopologicalOperator.ConstructUnion((IEnumGeometry)geometryBag);
            IPolygon resultPolygon = (IPolygon)pTopologicalOperator;
            return resultPolygon;
        }




        //不要删，创建多边形
        //public static Dictionary<int, IPolygon> CreatePolygons58(List<LineInfo58> lfs, ISpatialReference sr)
        //{
        //    int iPartIndex = lfs.Last().PartIndex;
        //    Dictionary<int, IPolygon> polygons = new Dictionary<int, IPolygon>();
        //    for (int i = 1; i <= iPartIndex; i++)
        //    {
        //        var bigcoors = lfs.Where(v => v.isCoor && v.PartIndex == i);
        //        var max_pri = bigcoors.Last().pri;
        //        List<WKSPoint[]> ringPoints = new List<WKSPoint[]>();
        //        for (int j = 1; j <= max_pri; j++)
        //        {
        //            var wksPoints = bigcoors.Where(v => v.pri == j).Select(g => g.WksPoint).ToList();
        //            var rstPt = wksPoints.First(); var lstPt = wksPoints.Last();
        //            if (rstPt.X != lstPt.X || rstPt.Y != lstPt.Y) wksPoints.Add(rstPt);
        //            ringPoints.Add(wksPoints.ToArray());
        //        }
        //        Int32 result;
        //        IPolygon polygon = null;
        //        if (max_pri == 1)
        //        {
        //            polygon = esriCreation.Factory.NewPolygon(sr, ringPoints[0], out result);
        //        }
        //        else
        //        {
        //            polygon = esriCreation.Factory.NewPolygon(sr, ringPoints[0], ringPoints.Where((p, n) => n > 0), out result);
        //        }
        //        polygons.Add(i, polygon);
        //    }
        //    return polygons;
        //}



        /// <summary>
        /// 根据点集创建多边形(一个外环，可挖空（1个或0个内环）)
        /// </summary>
        /// <param name="sr">坐标系</param>
        /// <param name="extPoints">外环点</param>
        /// <param name="innerPointList">内环点</param>
        /// <param name="result">创建情况</param>
        /// <returns></returns>
        public static IPolygon NewPolygon
            (
            ISpatialReference sr,
            WKSPoint[] extPoints, //外环点集
            IEnumerable<WKSPoint[]> innerPointList,//内环点集
            out Int32 result
            )
        {
            //创建一个多边形
            var polygon = NewPolygon(sr, extPoints, out result);

            if (null == polygon) //如果创建失败
            {
                result = Constants.EC11704;
                return null;
            }

            //获取polygon所有外环的集合
            var geometryCollection = (IGeometryCollection)polygon;

            //根据点集，创建内环
            List<IRing2> interRings = new List<ESRI.ArcGIS.Geometry.IRing2>(innerPointList.Count());
            foreach (var arrPoints in innerPointList)
            {
                var interRing = NewInteriorRing(arrPoints, true, out result);
                if (interRing != null)
                    interRings.Add(interRing);
                else
                {
                    //MessageBox.Show("无法生成内环！");
                    result = Constants.EC11705; return null;
                }
            }

            object obj = Type.Missing;

            //遍历内环集合中的每一个内环
            foreach (var interiorRing in interRings)
            {
                //添加内环到外环中
                geometryCollection.AddGeometry(interiorRing, ref obj, ref obj);
            }

            /**2011-08-17，星期三
             * 因揭阳坐标问题，生成的东西要调用Simple方法才行。
             */
            var topoOper = (ITopologicalOperator2)polygon;
            topoOper.IsKnownSimple_2 = false;
            if (!topoOper.IsSimple)//如果拓扑错误
            {
                topoOper.Simplify();//拓扑校正
            }

            if (!polygon.CanUse2(out result))
            {
                return null;
            }
            else
                return polygon;
        }





        /// <summary>
        /// 创建一个简单的（只有一个外环)的Polygon
        /// </summary>
        /// <param name="sr">坐标系统</param>
        /// <param name="extPoints">点集</param>
        /// <param name="result">创建情况</param>
        /// <returns></returns>
        public static IPolygon NewPolygon(
            ISpatialReference sr,
            WKSPoint[] extPoints,
            out Int32 result)
        {
            result = Constants.EC_NONE;
            //创建外环
            var ring1 = NewExteriorRing(extPoints, true, out result);
            if (null == ring1)
                return null;

            //创建空的polygon
            IGeometryBridge2 geometryBridge2 = new GeometryEnvironmentClass();
            IPolygon polygon = new PolygonClass();
            polygon.SpatialReference = sr;//设置控件参考
            var pointPolygon = (IGeometryCollection)polygon;
            System.Object missing = Type.Missing;

            pointPolygon.AddGeometry(ring1 as IGeometry, ref missing, ref missing);

            /**2011-08-17，星期三
             * 因揭阳坐标问题，生成的东西要调用Simple方法才行。
             */
            var topoOper = (ITopologicalOperator2)polygon;
            topoOper.IsKnownSimple_2 = false;
            if (!topoOper.IsSimple)//如果拓扑不正确
            {
                topoOper.Simplify();//拓扑校正
            }

            if (polygon.CanUse2(out result) == false)
            {
                return null;
            }
            else
                return polygon;
        }


        /// <summary>
        /// 创建一个内环InteriorRing,内环点的顺序是 anticlockwise
        /// </summary>
        /// <param name="points">点数组</param>
        /// <returns>点顺序正确返回ring,否则返回false</returns>
        public static IRing2 NewInteriorRing(WKSPoint[] points, Boolean autoClose, out Int32 result)
        {
            var ring = NewRing(points, autoClose, out result);
            //System.Diagnostics.Debug.Print("14A");
            if (ring == null)
            {
                //System.Diagnostics.Debug.Print("14B");
                return null;
            }

            if (ring.IsExterior == false) //内环
                return ring;
            else//如果是外环
            {
                //反转点集中的顺序
                var revPoints = points.Reverse().ToArray();
                //System.Diagnostics.Debug.Print("14C");
                ring = NewRing(revPoints, autoClose, out result);
                if (null == ring)
                {
                    //System.Diagnostics.Debug.Print("14D"); 
                    return null;
                }
                else
                {
                    if (ring.IsExterior == false)
                        return ring;
                    else
                    {
                        //System.Diagnostics.Debug.Print("14E");
                        result = Constants.EC11702; return null;
                    }
                }
            }

            #region 旧代码段，已注释
            //esriGeometry.IGeometryBridge2 geometryBridge2 = new esriGeometry.GeometryEnvironmentClass();
            //var ring1 = new esriGeometry.RingClass();
            //geometryBridge2.SetWKSPoints(ring1 as esriGeometry.IPointCollection4, ref points);

            //if (ring1.IsClosed == false && autoClose) ring1.Close();
            //if (ring1.IsEmpty) { result = constants.EC11700; return null; }
            //if (!ring1.IsClosed) { result = constants.EC11701; return null; }
            //if (!ring1.IsExterior) { result = constants.EC_NONE; return ring1; }


            //if (!ring1.IsEmpty && !ring1.IsExterior && ring1.IsClosed) return ring1;

            //var revPoints = points.Reverse().ToArray();
            //var ring2 = new esriGeometry.RingClass();
            //geometryBridge2.SetWKSPoints(ring2 as esriGeometry.IPointCollection4, ref revPoints);

            //if (!ring2.IsEmpty && !ring2.IsExterior && ring2.IsClosed) return ring2;

            //return null;
            #endregion

        }


        /// <summary>
        /// 创建一个“外部Ring”，即点的顺序是顺时针的(ring orientation is clockwise)
        /// 外环顺时针 内环逆时针
        /// </summary>
        /// <param name="points">点数姐</param>
        /// <param name="autoClose">是否自动闭合？</param>
        /// <returns>正顺序（顺时针）正确返回Ring,否则返回null</returns>
        public static IRing2 NewExteriorRing(WKSPoint[] points, Boolean autoClose, out Int32 result)
        {
            var ring = NewRing(points, autoClose, out result);

            if (ring == null)
                return null;

            if (ring.IsExterior) //如果是外环，顺时针
                return ring;
            else//如果是内部的，逆时针
            {
                //反转序列中元素的顺序（即将逆时针转换为顺时针），外环，顺时针；内环，逆时针
                var revPoints = points.Reverse().ToArray();
                //MessageBox.Show("点号逆转！");
                ring = NewRing(revPoints, autoClose, out result);
                if (null == ring)
                {
                    //MessageBox.Show("逆转后无法生成"); 
                    return null;
                }
                else
                {
                    if (ring.IsExterior) //如果是外部的
                        return ring;
                    else
                    {
                        result = Constants.EC11702;
                        return null;
                    }
                }
            }
            #region 旧代码段，已注释，有参考作用
            ///**请参考：
            // * IRing.IsExterior Property
            // * ms-help://ESRI.EDNv9.3/esriGeometry/html/IRing_IsExterior.htm
            // * GeometryEnvironmentClass Class
            // * ms-help://ESRI.EDNv9.3/esriGeometry/html/GeometryEnvironment.htm
            // * GeometryEnvironmentClass 是一个Singleton
            // */
            //esriGeometry.IGeometryBridge2 geometryBridge2 = new esriGeometry.GeometryEnvironmentClass();

            //var ring1 = new esriGeometry.RingClass();

            //geometryBridge2.SetWKSPoints(ring1 as esriGeometry.IPointCollection4, ref points);

            //if (!ring1.IsEmpty && ring1.IsExterior && ring1.IsClosed) return ring1;

            //var revPoints = points.Reverse().ToArray();

            //var ring2 = new esriGeometry.RingClass();

            //geometryBridge2.SetWKSPoints(ring2 as esriGeometry.IPointCollection4, ref revPoints);

            //if (!ring2.IsEmpty && ring2.IsExterior && ring2.IsClosed) return ring2;

            //return null;
            #endregion
        }


        /// <summary>
        /// 创建一个Ring，并闭合
        /// </summary>
        /// <param name="points">点集/</param>
        /// <param name="outoClose">如果提供的点集不闭合，是否自动闭合</param>
        /// <param name="result">创建的情况</param>
        /// <returns>成功返回Ring,否则返回null</returns>
        internal static IRing2 NewRing(WKSPoint[] points, Boolean autoClose, out Int32 result)
        {
            result = Constants.EC_NONE;//成功，无错误

            IGeometryBridge2 geometryBridge2 = new GeometryEnvironmentClass();
            var ring1 = new RingClass();
            geometryBridge2.SetWKSPoints(ring1 as IPointCollection4, ref points);

            //如果ring1没有闭合 && 自动闭合
            if (!ring1.IsClosed && autoClose)
                ring1.Close();

            if (ring1.IsEmpty) //empty
            {
                result = Constants.EC11700;
                return null;
            }
            if (ring1.IsClosed == false) //没有闭合
            {
                result = Constants.EC11701;
                return null;
            }

            return ring1;
        }


        #endregion


        #region 坐标系

        public ISpatialReference GetSpatialReference_Xian1980_3_38()
        {
            SpatialReferenceEnvironmentClass srec = new SpatialReferenceEnvironmentClass();
            return (ISpatialReference)srec.CreateProjectedCoordinateSystem(Constants.Prj38Code);
        }


        /// <summary>
        /// 获取featureClass的坐标系
        /// </summary>
        /// <param name="pFeatureClass"></param>
        /// <returns></returns>
        public ISpatialReference GetSpatialReference_from_featureClass(IFeatureClass pFeatureClass)
        {
            IGeoDataset pGeoDataset = pFeatureClass as IGeoDataset;

            return pGeoDataset.SpatialReference;

        }

        #endregion


        #region GP工具

        //用gp工具最好设置license控件的权限为ArcInfo，engine93最好不要用代码设置权限
        //设置权限的时候注意，如果设置了2个权限，如editor和ArcInfo，会以最低的权限为准
        //如果用代码设置以上2个权限，会以第一个设置的权限为准？

        Clip clipTool = new Clip();//裁剪工具  //一定要放在这里
        Geoprocessor gp = new Geoprocessor();//Geoprocessor 很好用

        /// <summary>
        /// 用目标图层截取输入的图层(返回featureClass)
        /// </summary>
        /// <param name="strInputLayerName"></param>
        /// <param name="pClipFeatureClass"></param>
        /// <returns>IFeatureClass</returns>
        public IFeatureClass Clip_GP(IFeatureClass inputFeatureClass, IFeatureClass clipFeatureClass, string output_path)
        {

            if (inputFeatureClass == null) return null;//如果输入图层不存在，退出

            clipTool.in_features = inputFeatureClass;//输入（被裁剪）FeatureClass
            clipTool.clip_features = clipFeatureClass;//裁剪FeatureClass
            clipTool.out_feature_class = output_path;//输出路径+文件名
            try
            {
                //开始裁剪，保存到指定路径
                IGeoProcessorResult pGeoProcessorResult = (IGeoProcessorResult)gp.Execute(clipTool, null);
                Console.WriteLine(pGeoProcessorResult.GetResultMessages());
            }
            catch (Exception err)
            {
                //MessageBox.Show("Clip_GP:" + err.ToString(), "提示！", MessageBoxButtons.OK, MessageBoxIcon.Information);
                Debug.Print("Clip_GP：" + err.ToString());
                return null;
            }

            IFeatureClass resultFeatureClass = null;

            try
            {
                IWorkspaceFactory pWorkspaceFactory = new ShapefileWorkspaceFactoryClass();
                IWorkspace pWorkspace = pWorkspaceFactory.OpenFromFile(System.IO.Path.GetDirectoryName(output_path), 0);
                IFeatureWorkspace pFeatureWorkspace = (IFeatureWorkspace)pWorkspace;
                string fileName = System.IO.Path.GetFileName(output_path);
                resultFeatureClass = pFeatureWorkspace.OpenFeatureClass(fileName);
            }
            catch (System.Exception ex)
            {
                Debug.Print("Clip_GP：" + ex.ToString());
                return null;
            }

            
            return resultFeatureClass;
        }


        Erase eraseTool = new Erase();

        //进行erase操作，并更新数据库
        public IFeatureClass Erase_GP(IFeatureClass eraseFeatureClass, IFeatureClass inputFeatureClass, string output_path)
        {
            //要设置license控件的权限为ArcInfo，engine93最好不要用代码设置权限
            //设置权限的时候注意，如果设置了2个权限，如editor和ArcInfo，会以最低的权限为准

            Console.WriteLine(output_path);

            Console.WriteLine(System.IO.Path.GetDirectoryName(eraseFeatureClass.AliasName));
            Console.WriteLine(inputFeatureClass.AliasName);


            Console.WriteLine(output_path);
            Console.WriteLine(System.IO.Path.GetFileName(output_path));


            //IFeatureClass outputFeatureClass = eraseLayerClass.CreateFeatureClass(Factory.NewFeatureWorkspace(System.IO.Path.GetDirectoryName(output_path)), System.IO.Path.GetFileNameWithoutExtension(output_path));



            if (eraseFeatureClass == null || inputFeatureClass == null || output_path == string.Empty)
                return null;

            eraseTool.erase_features = eraseFeatureClass;
            eraseTool.in_features = inputFeatureClass;
            eraseTool.out_feature_class = output_path;
            //eraseTool.out_feature_class = outputFeatureClass;



            if (eraseTool == null || gp == null)
                Console.WriteLine("eraseTool或gp为空");


            try
            {
                Console.WriteLine(eraseTool.ToolboxName);
                //IGeoProcessorResult geoProcessorResult = (IGeoProcessorResult)gp.Execute(eraseTool, null);
                gp.Execute(eraseTool, null);
                //Console.WriteLine(geoProcessorResult.GetResultMessages());//用这个会出错
            }
            catch (COMException ex)
            {
                Console.WriteLine(ex.ToString());
                return null;
            }

            return NewFeatureClass(output_path);

        }
        
        
        #endregion


        #region 打印

        [DllImport("GDI32.dll")]
        public static extern int GetDeviceCaps(int hdc, int nIndex);

        [DllImport("GDI32.dll")]
        public static extern int CreateDC(string strDriver, string strDevice, string strOutput, IntPtr pData);

        [DllImport("User32.dll")]
        public static extern int ReleaseDC(int hWnd, int hDC);

        #region 打印方法一（ae93官方例子）(会将所有内容缩放到可打印区域内，即一定不会有内容丢失)
        //打印activeView，map或pageLayout
        public void PrintActiveViewParameterized(long iResampleRatio, IMapDocument _mapDocument)
        {

            //打印还可以参考http://edndoc.esri.com/arcobjects/9.0/default.asp?URL=/arcobjects/9.0/samples/cartography/printing_and_exporting/printactiveview.htm

            //不能全部打印,即打印的内容因为超出打印机的打印区域，出结果的时候被分成多份:
            //方法一：
            //this.axPageLayoutControl1.Page.FormID = esriPageFormID.esriPageFormA4;//注释类似的代码
            //mapDocument.PageLayout.Page.FormID = esriPageFormID.esriPageFormSameAsPrinter;//修改为这样？
            //方法二：
            //试试设置ArcMap-->page and print setting-->勾选use printer page setting

            // ResampleRatio :得新取样比率，应该跟打印质量相关
            // Raster :光栅
            //  margin：页边距
            // How to set output image quality 

            /* Prints the Active View of the document to selected output format. */
            //          
            IActiveView docActiveView = _mapDocument.ActiveView;
            IPrinter docPrinter;
            long iPrevOutputImageQuality;
            IOutputRasterSettings docOutputRasterSettings;
            tagRECT deviceRECT;
            IPaper docPaper;
            /* printdocument is from the .NET assembly system.drawing.printing */
            System.Drawing.Printing.PrintDocument sysPrintDocumentDocument;


            short iNumPages;
            IEnvelope docPrinterBounds;
            IEnvelope VisibleBounds;


            docPrinterBounds = new EnvelopeClass();
            VisibleBounds = new EnvelopeClass();

            /**The following function shows how to properly set the Output Image Quality (raster resampling ratio)
             * for a given active view. The output image quality should be set just before exporting or printing 
             * at the given output image quality. 
             * 注意下面的说明
             * For the sake of consistency, a developer should always retain the original resampling ratio before 
             * changing it and set it back to the original resampling 
             * ratio after finishing the export or print task. */

            // save the previous output image quality, so that when the export is complete it will be set back.
            docOutputRasterSettings = docActiveView.ScreenDisplay.DisplayTransformation as IOutputRasterSettings;
            iPrevOutputImageQuality = docOutputRasterSettings.ResampleRatio;

            SetOutputQuality(docActiveView, iResampleRatio);


            /* Now we need to get the default printer name.  Since this is a generic command,
             * we can't use the printername property of the document.  So instead, we use the 
             * System.Drawing.Printing objects to find the default printer.
             */
            docPrinter = new EmfPrinterClass();
            sysPrintDocumentDocument = new System.Drawing.Printing.PrintDocument();
            docPaper = new PaperClass();

            /* testing to see if printer instantiated in sysPrintDocumentDocument is the 
             * default printer.  It SHOULD be, but this is just a reality check.
             */
            bool isDefault = sysPrintDocumentDocument.PrinterSettings.IsDefaultPrinter;

            if (isDefault)
            {
                //Set docPaper's printername to the printername of the default printer
                docPaper.PrinterName = sysPrintDocumentDocument.PrinterSettings.PrinterName;


            }
            else
            {
                //if we get an unexpected result, return.
                //MessageBox.Show("Error getting default printer info, exiting...");
                return;
            }


            //make sure the paper orientation is set to the orientation matching the current view.
            docPaper.Orientation = _mapDocument.PageLayout.Page.Orientation;

            /* Now assign docPrinter the paper and with it the printername.  This process is two steps
             * because you cannot change an IPrinter's printer except by passing it as a part of 
             * the IPaper.  That's why we setup docPrinter.Paper.PrinterName first.
             */
            docPrinter.Paper = docPaper;

            //set the spoolfilename (this is the job name that shows up in the print queue)
            docPrinter.SpoolFileName = "PrintActiveViewSample";

            // Get the printer's hDC, so we can use the Win32 GetDeviceCaps fuction to
            //  get Printer's Physical Printable Area x and y margins
            int hInfoDC;
            hInfoDC = CreateDC(docPrinter.DriverName, docPrinter.Paper.PrinterName, "", IntPtr.Zero);


            // Find out how many printer pages the output will cover. 


            if (_mapDocument.ActiveView is IPageLayout)
            {

                _mapDocument.PageLayout.Page.PrinterPageCount(docPrinter, 0, out iNumPages);

            }
            else
            {
                iNumPages = 1;
            }

            //这里应该改为1？如果有多页的话会打印不出来？
            //ae10官方例子里面是1
            //不过貌似设置为1后打印不了
            for (short lCurrentPageNum = 0; lCurrentPageNum < iNumPages; lCurrentPageNum++)
            {

                //里面的0应该改为1？
                //9.0和10.0 ae的例子里面是1
                _mapDocument.PageLayout.Page.GetDeviceBounds(docPrinter, lCurrentPageNum, 0, docPrinter.Resolution, docPrinterBounds);

                //Transfer PrinterBounds envelope, offsetting by PHYSICALOFFSETX
                // the Win32 constant for PHYSICALOFFSETX is 112
                // the Win32 constant for PHYSICALOFFSETY is 113
                deviceRECT.bottom = (int)(docPrinterBounds.YMax - GetDeviceCaps(hInfoDC, 113));
                deviceRECT.left = (int)(docPrinterBounds.XMin - GetDeviceCaps(hInfoDC, 112));
                deviceRECT.right = (int)(docPrinterBounds.XMax - GetDeviceCaps(hInfoDC, 112));
                deviceRECT.top = (int)(docPrinterBounds.YMin - GetDeviceCaps(hInfoDC, 113));

                // Transfer offsetted PrinterBounds envelope back to the deviceRECT
                docPrinterBounds.PutCoords(0, 0, deviceRECT.right - deviceRECT.left, deviceRECT.bottom - deviceRECT.top);



                if (_mapDocument.ActiveView is IPageLayout)
                {
                    //get the visible bounds for this layout, based on the current page number.
                    _mapDocument.PageLayout.Page.GetPageBounds(docPrinter, lCurrentPageNum, 0, VisibleBounds);
                }
                else
                {
                    //if it's not a page layout, export whatever's on screen at the printer's dpi.

                    //get the page
                    IPage pPage;
                    pPage = _mapDocument.PageLayout.Page;

                    //get paper object
                    docPaper = docPrinter.Paper;
                    if (docPaper == null)
                    {
                        //MessageBox.Show("no paper defined");
                        return;
                    }

                    //create an envelope for the bounds of the printer's page size in device units.
                    IEnvelope pDeviceFrame;
                    pDeviceFrame = new EnvelopeClass();
                    pPage.GetDeviceBounds(docPrinter, 1, 0, docPrinter.Resolution, pDeviceFrame);

                    //create and populate an envelope with the bounds of the printer page.
                    WKSEnvelope wksdevice;
                    pDeviceFrame.QueryWKSCoords(out wksdevice);

                    //transfer the envelope to the deviceRECT. 
                    deviceRECT.left = (int)Math.Round(wksdevice.XMin);
                    deviceRECT.top = (int)Math.Round(wksdevice.YMin);
                    deviceRECT.right = (int)Math.Round(wksdevice.XMax);
                    deviceRECT.bottom = (int)Math.Round(wksdevice.YMax);

                    //since this is a data view, not a pagelayout, we don't need VisibleBounds, so set it to NULL.
                    VisibleBounds = null;

                }


                //Here's where the printing actually begins:
                //==========================================
                //The docPrinter.StartPrinting method returns the hDC of the printer, which we then
                //use as the hDC parameter of activeview.output.  ActiveView.Output is the function that
                //draws the content on the active view, at the specified resolution, to the deviceRECT specified.
                //VisibleBounds can be null, which means "print the active view", or can be set to a zoom extent.
                if (iNumPages == 1)
                {
                    VisibleBounds = null;
                }
                _mapDocument.ActiveView.Output(docPrinter.StartPrinting(docPrinterBounds, 0), docPrinter.Resolution, ref deviceRECT, VisibleBounds, null);

                //here we call FinishPrinting, which actually flushes the output to the printer.
                docPrinter.FinishPrinting();

                //now set the output quality back to the previous output quality.
                SetOutputQuality(docActiveView, iPrevOutputImageQuality);

            }
            //release the DC...
            ReleaseDC(0, hInfoDC);
        }

        //设置输出的属性
        private void SetOutputQuality(IActiveView docActiveView, long iResampleRatio)
        {
            /* This function sets OutputImageQuality for the active view.  If the active view is a pagelayout, then
             * it must also set the output image quality for EACH of the Maps in the pagelayout.
             */
            IGraphicsContainer docGraphicsContainer;
            IElement docElement;
            IOutputRasterSettings docOutputRasterSettings;
            IMapFrame docMapFrame;
            IActiveView tmpActiveView;

            if (docActiveView is IMap)
            {
                docOutputRasterSettings = docActiveView.ScreenDisplay.DisplayTransformation as IOutputRasterSettings;
                docOutputRasterSettings.ResampleRatio = (int)iResampleRatio;
            }
            else if (docActiveView is IPageLayout)
            {
                //assign ResampleRatio for PageLayout
                docOutputRasterSettings = docActiveView.ScreenDisplay.DisplayTransformation as IOutputRasterSettings;
                docOutputRasterSettings.ResampleRatio = (int)iResampleRatio;
                //and assign ResampleRatio to the Maps in the PageLayout
                docGraphicsContainer = docActiveView as IGraphicsContainer;
                docGraphicsContainer.Reset();

                docElement = docGraphicsContainer.Next();
                while (docElement != null)
                {
                    if (docElement is IMapFrame)
                    {
                        docMapFrame = docElement as IMapFrame;
                        tmpActiveView = docMapFrame.Map as IActiveView;
                        docOutputRasterSettings = tmpActiveView.ScreenDisplay.DisplayTransformation as IOutputRasterSettings;
                        docOutputRasterSettings.ResampleRatio = (int)iResampleRatio;
                    }
                    docElement = docGraphicsContainer.Next();
                }

                docMapFrame = null;
                docGraphicsContainer = null;
                tmpActiveView = null;
            }
            docOutputRasterSettings = null;

        }
        #endregion

        #region 打印方法二（ae调用打印机需要的最少步骤）（不能打印多页？）(不会将所有内容缩放到可打印区域内，可能会有内容丢失，即如果内容的范围大于可打印的范围,会有内容丢失)
        public void PrintActiveView(IMapDocument _mapDocument)
        {

            IPrinter pPrinter = _mapDocument.Printer;//获取要打印的对象

            IEnvelope pPrinterBounds = new EnvelopeClass();//打印范围

            tagRECT deviceRECT;
            IEnvelope pVisibleBounds = null;

            _mapDocument.PageLayout.Page.GetDeviceBounds(pPrinter, 1, 0, pPrinter.Resolution, pPrinterBounds);

            deviceRECT.bottom = (int)(pPrinterBounds.YMax);
            deviceRECT.left = (int)(pPrinterBounds.XMin);
            deviceRECT.right = (int)(pPrinterBounds.XMax);
            deviceRECT.top = (int)(pPrinterBounds.YMin);

            if (_mapDocument.ActiveView is IPageLayout)
            {
                pVisibleBounds = new EnvelopeClass();
                _mapDocument.PageLayout.Page.GetPageBounds(pPrinter, 1, 0, pVisibleBounds);
            }

            int hDC;
            hDC = pPrinter.StartPrinting(pPrinterBounds, 0);

            _mapDocument.ActiveView.Output(hDC, pPrinter.Resolution, ref deviceRECT, pVisibleBounds, null);
            
            pPrinter.FinishPrinting();
            
        }
        #endregion

        #endregion




    }
}
